package service

import (
	"echo-utils/global"
	"fmt"
	"reflect"
	"time"
)

type Job struct {
	Task interface{}
}

var (
	MaxWorker = 4
	JobQueue  chan Job
)

type Worker struct {
	id         int
	WorkerPool chan chan Job
	JobChannel chan Job
	exit       chan bool
}

func NewWorker(workerPool chan chan Job, id int) Worker {
	fmt.Printf("new a worker(%d)\n", id)
	return Worker{
		id:         id,
		WorkerPool: workerPool,
		JobChannel: make(chan Job),
		exit:       make(chan bool),
	}
}

// 监听任务和结束信号
func (w Worker) Start() {
	go func() {
		for {
			w.WorkerPool <- w.JobChannel
			global.Logger.Infof("注册Job通道到工作池：%v", w)
			select {
			case job := <-w.JobChannel: //收到任务
				global.Logger.Infof("收到工作任务：%v", job)
				// 通过反射调用任务的run方法
				r_value := reflect.ValueOf(job.Task)
				r_method := r_value.MethodByName("Run")
				r_args := make([]reflect.Value, 0)
				r_method.Call(r_args)
			case <-w.exit:
				global.Logger.Infof("收到结束信号，结束worker:%v", w)
				return
			}
		}
	}()
}

func (w Worker) Stop() {
	go func() {
		w.exit <- true
	}()
}

// 排程中心
type Scheduler struct {
	WorkerPool chan chan Job
	MaxWorkers int
	Workers    []*Worker
}

// 创建排程中心
func NewScheduler(maxWorkers int) *Scheduler {
	pool := make(chan chan Job, maxWorkers)
	return &Scheduler{WorkerPool: pool, MaxWorkers: maxWorkers}
}

// 工作池的初始化
func (s *Scheduler) Create() {
	workers := make([]*Worker, s.MaxWorkers)
	for i := 0; i < s.MaxWorkers; i++ {
		worker := NewWorker(s.WorkerPool, i)
		worker.Start()
		workers[i] = &worker
	}
	s.Workers = workers
	go s.schedule()
}

// 工作池的关闭
func (s *Scheduler) Shutdown() {
	workers := s.Workers
	for _, w := range workers {
		w.Stop()
	}
	time.Sleep(time.Second)
	close(s.WorkerPool)
}

// 排程
func (s *Scheduler) schedule() {
	for {
		select {
		case job := <-JobQueue:
			global.Logger.Infof("从队列中取到任务：%v", job)
			go func(job Job) {
				jobChannel := <-s.WorkerPool
				global.Logger.Infof("从工作池获取到可用job通道：%v", reflect.TypeOf(jobChannel))
				jobChannel <- job
				global.Logger.Info("将job加入job通道")
			}(job)
		}
	}
}
